iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0

控制反轉 Inversion of Control (IOC)

控制反轉是一種程式設計的方式。它的精神在於程式中所需要的輔助物件,並不是在自己的類別中建立,而是由外部控制的。建立好後,將其傳遞給主程式,這個動作稱為依賴注入,是控制反轉的實現方式。

  • 將 Object 的控制權交給外部的 Spring 容器來管理

依賴注入 dependency injection (DI)

實現控制反轉的方式,Spring 的設計目標之一是為了解隅,利用依賴抽象而非依賴實例的方式,因此設計了依賴注入(DI)。

  • @Component , @RestController @Service … 等註各類解加在 class 上,將class交給Spring 管理,這些也就是在 Spring Boot 中所謂的 Bean (後面章節會有詳細介紹)
  • @Autowired 將被管理的 Bean 注入

應用範例

  • 舉例來說有個物件專門來處理寄送訊息叫做 Sender ,我們需要使用到這個物件就必須透過 new 方法來建立出來,假設今天原本的 Sender 有問題更改成別種 Sender ,就必須有建立這個物件的地方都需要修改一遍,這時候改成用 DI 的方式就會比較容易維護及更動。

沒有使用 DI 方式,使用 New 方法來建立物件並引用

public class Notify{
    private Sender sender = new Sender();
    
    // 如果需要更換方法,每個有用到的地方都要改
    // private NewSender sender = new NewSender();
    
    public void Send() {
        sender.print("Hi! I'm Sean")
    }
}

@Autowired 注入單一實做物件

將 Sender 交給 Spring 容器管理,使用 @Autowired 注入去使用,等於是透過 Spring 去建立物件出來

@Component
public class Notify{

    // 如果要更改方法,往上註冊為 bean 的部分修改就可以,注入部分不需要改變
    @Autowired
    private Sender sender;

    public void Send() {
        sender.print("Hi! I'm Sean")
    }
}

@Autowired 注入介面內含多個已實做物件

如果我們可能有多種 Sender 需要去實踐,可以用 interface 來建立一個介面去分成不同方法實踐

@Component
public interface Sender {
	void send(String msg);
}
@Component
public class GoogleMailSender implements Sender {
		@Override
		public void send(String msg) {
				System.out.println("內容: " + msg + " 我用 Google 郵件寄出了!!")
		}
}
@Component
public class OutlookMailSender implements Sender {
		@Override
		public void send(String msg) {
				System.out.println("內容: " + msg + " 我用 Outlook 郵件寄出了!!")
		}
}

可以將 @Component 選擇注入其中一種,Spring 容器會自動幫我們選擇我們有注入的那個,但如果兩種都注入,就會出現錯誤,所以要再選擇用 @Qualifier(”bean 名稱”) 註解來指定要入住哪個

** 注意注入容器的 bean 名稱開頭是小寫

@Component
public class Notify{

    @Autowired
    @Qualifer("GoogleMailSender") //  @Qualifer("outlookMailSender")
    private Sender sender;

    public void Send() {
        sender.print("Hi! I'm Sean")
    }
}

總結:

利用 IOC 和 DI 可以有以下優點:

  • 鬆耦合

class 之間的鬆耦合,降低各個 class 之間的關聯性。

像是假設我們本來得在 Notify 中去指定要使用的是哪家廠牌的 MailSender(可能是 google, yahoo...) 而這就會讓 Notify 和 MailSender 的耦合變大,但使用了 Spring IoC 之後,不需要了解這個 Sender 是哪種,只要確定有被正確注入某種可以使用的 MailSender。

  • 統一生命週期管理

交由 Spring 容器來管理這些物件的生命週期,減少不必要的引用。

因為我們將 MailSender 這個 object 改成是交由 Spring 容器來管理,因此 Spring 就會負責物件的創建、初始化、以及銷毀,所以就不需要我們親自去處理這件事情。

  • 方便測試程式

可以方便注入至所需要測試的程式中

所有的 object 都是由外部的 Spring 容器來做管理,因此我們就可以輕鬆在測試程式內在測試的過程中,將 Spring 容器中的 object 給替換掉,容易的使用像是 Mock 的技術。


Ref:

相關文章也會同步更新我的部落格,有興趣也可以在裡面找其他的技術分享跟資訊。


上一篇
Day 1 - Spring Boot 介紹
下一篇
Day 3 - Bean 介紹及常見應用
系列文
關於我和 Spring Boot 變成家人的那件事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言